/****************************************************************************
*
* Copyright (c) 2023  C*Core -   All Rights Reserved
*
* THIS SOFTWARE IS DISTRIBUTED "AS IS, " AND ALL WARRANTIES ARE DISCLAIMED,
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* PROJECT     : CCFC2011BC
* DESCRIPTION : Setup of IVPR to point to the EXCEPTION_HANDLERS memory area
 *               defined in the linker command file.
 *               Default setup of the IVORxx registers.
* HISTORY     : Initial version.
* @file     Exceptions.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
*
*****************************************************************************/

#include "Exceptions.h" /* Implement functions from this file */
#include "console.h"

/*----------------------------------------------------------------------------*/
/* Function Implementations                                                   */
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
static void IVOR2_ISR(void) /* PRQA S 3219 */
{
    PSPRINTF("\r\n *********in IVOR2************ \r\n");
}
#pragma push /* Save the current state */
/* Symbol EXCEPTION_HANDLERS is defined in the application linker command file (.lcf) 
   It is defined to the start of the code memory area used for the .__exception_handlers section. 
*/
/*lint -esym(752, EXCEPTION_HANDLERS) */
__declspec (section ".__exception_handlers") extern long EXCEPTION_HANDLERS; /* PRQA S 5209 */
#pragma force_active on
#pragma function_align 16 /* We use 16 bytes alignment for Exception handlers */
__declspec(interrupt)
__declspec (section ".__exception_handlers")
void EXCEP_DefaultExceptionHandler(void)
{

}
static void EXCEP_DefaultExceptionHandler0(void) /* PRQA S 3219 */
{
    PSPRINTF("\r\n *********in IVOR0************ \r\n");
}
void EXCEP_DefaultExceptionHandler1(void) /* PRQA S 3408 */
{
    PSPRINTF("\r\n *********in IVOR1************ \r\n");
}
__asm void EXCEP_DefaultExceptionHandler2(void) /* PRQA S 1006, 3408 */
{
nofralloc
prolog:
    stwu    r1, -0x50 (r1)    /* Create stack frame */
    stw r0,  0x24 (r1)        /* Store r0 working register  */

    /* Save SRR0 and SRR1 */
    mfsrr1  r0                /* Store SRR1 (must be done before enabling EE) */
    stw     r0,  0x10 (r1)
    mfsrr0  r0                /* Store SRR0 (must be done before enabling EE) */
    stw     r0,  0x0C (r1)
    
    stw     r3,  0x28 (r1)    /* Store r3 */
    /* Save rest of context required by EABI */
    stw     r12, 0x4C (r1)      /* Store r12 */
    stw     r11, 0x48 (r1)      /* Store r11 */
    stw     r10, 0x44 (r1)      /* Store r10 */
    stw     r9,  0x40 (r1)      /* Store r9 */
    stw     r8,  0x3C (r1)      /* Store r8 */
    stw     r7,  0x38 (r1)      /* Store r7 */
    stw     r6,  0x34 (r1)      /* Store r6 */
    stw     r5,  0x30 (r1)      /* Store r5 */
    stw     r4,  0x2C (r1)      /* Store r4 */
    mfcr    r0                  /* Store CR */
    stw     r0,  0x20 (r1)
    mfxer   r0                  /* Store XER */
    stw     r0,  0x1C (r1)
    mfctr   r0                  /* Store CTR */
    stw     r0,  0x18 (r1)
    mflr    r0                  /* Store LR */
    stw     r0,  0x14 (r1)
  
    /* Branch to ISR handler */  
    mr      r3, r1
    /* Create stack frame */
    stwu    r1, -0x8 (r1)
    lis     r0, IVOR2_ISR@h /* PRQA S 0289 */
    ori     r0, r0, IVOR2_ISR@l
    mtlr      r0
    blrl
    /* Restore space on stack */
    addi    r1, r1, 0x8 
    //addi    r31, r31, 0x8 

epilog:
    /* Restore context required by EABI (except working registers) */
    lwz     r0,  0x14 (r1)      /* Restore LR */
    mtlr    r0
    lwz     r0,  0x18 (r1)      /* Restore CTR */
    mtctr   r0
    lwz     r0,  0x1C (r1)      /* Restore XER */
    mtxer   r0
    lwz     r0,  0x20 (r1)      /* Restore CR */
    mtcrf   0xff, r0
    lwz     r5,  0x30 (r1)      /* Restore r5 */
    lwz     r6,  0x34 (r1)      /* Restore r6 */
    lwz     r7,  0x38 (r1)      /* Restore r7 */
    lwz     r8,  0x3C (r1)      /* Restore r8 */
    lwz     r9,  0x40 (r1)      /* Restore r9 */
    lwz     r10, 0x44 (r1)      /* Restore r10 */
    lwz     r11, 0x48 (r1)      /* Restore r11 */
    lwz     r12, 0x4C (r1)      /* Restore r12 */

    /* Disable processor recognition of interrupts */
    wrteei  0
    
    /* Ensure interrupt flag has finished clearing */
    mbar    0

    /* Restore Working Registers */
    lwz     r3,  0x28 (r1)      /* Restore r3 */
    lwz     r4,  0x2C (r1)      /* Restore r4 */

    /* Retrieve SRR0 and SRR1 */
    lwz     r0,  0x0C (r1)      /* Restore SRR0 */
    mtsrr0  r0
    lwz     r0,  0x10 (r1)      /* Restore SRR1 */
    mtsrr1  r0

    /* Restore Other Working Registers */
    lwz     r0,  0x24 (r1)      /* Restore r0 */

    /* Restore space on stack */
    addi    r1, r1, 0x50

    /* End of Interrupt */
    rfi
}
void EXCEP_DefaultExceptionHandler3(void) /* PRQA S 3408 */
{
    PSPRINTF("\r\n *********in IVOR3************ \r\n");
}
void EXCEP_DefaultExceptionHandler4(void) /* PRQA S 3408 */
{
    PSPRINTF("\r\n *********in IVOR4************ \r\n");
}
void EXCEP_DefaultExceptionHandler5(void) /* PRQA S 3408 */
{
    PSPRINTF("\r\n *********in IVOR5************ \r\n");
}
void EXCEP_DefaultExceptionHandler6(void) /* PRQA S 3408 */
{
    PSPRINTF("\r\n *********in IVOR6************ \r\n");
}
#pragma force_active off
#pragma pop

__asm void EXCEP_InitExceptionHandlers(void) /* PRQA S 1006 */
{
	nofralloc

    /* Set the IVPR to the Exception Handlers memory area defined in the lcf file */ 
    lis     r0, EXCEPTION_HANDLERS@h
    ori     r0, r0, EXCEPTION_HANDLERS@l
    mtivpr  r0

    /* Set all IVOR registers to the Default Exception Handler */
    lis     r0, EXCEP_DefaultExceptionHandler0@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler0@l

#if !defined(Z0H_CORE)
    /* IVORx registers are "hard-wired" in the e200z0 and z0h cores */

    /* IVOR0 Critical input (SPR 400) */
    mtivor0 r0
    /* IVOR1 Machine check interrupt (SPR 401) */
    lis     r0, EXCEP_DefaultExceptionHandler1@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler1@l
    mtivor1 r0
    /* IVOR2 Data storage interrupt (SPR 402) */
    lis     r0, EXCEP_DefaultExceptionHandler2@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler2@l
    mtivor2 r0
    /* IVOR3 Instruction storage interrupt (SPR 403) */
    lis     r0, EXCEP_DefaultExceptionHandler3@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler3@l
    mtivor3 r0
    /* IVOR4 External input interrupt (SPR 404) */
    mtivor4 r0
    /* IVOR5 Alignment interrupt (SPR 405) */
    lis     r0, EXCEP_DefaultExceptionHandler5@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler5@l
    mtivor5 r0
    /* IVOR6 Program interrupt (SPR 406) */
    lis     r0, EXCEP_DefaultExceptionHandler6@h
    ori     r0, r0, EXCEP_DefaultExceptionHandler6@l
    mtivor6 r0
    /* IVOR7 Floating-point unavailable interrupt (SPR 407) */
    mtivor7 r0
    /* IVOR8 System call interrupt (SPR 408) */
    mtivor8 r0
    /* IVOR9 Auxiliary processor (SPR 409) */
    mtivor9 r0
    /* IVOR10 Decrementer interrupt (SPR 410) */
    mtivor10 r0
    /* IVOR11 Fixed-interval timer interrupt (SPR 411) */
    mtivor11 r0
    /* IVOR12 Watchdog timer interrupt (SPR 412) */
    mtivor12 r0
    /* IVOR13 Data TLB error interrupt (SPR 413) */
    mtivor13 r0        
    /* IVOR14 Instruction TLB error interrupt (SPR 414) */
    mtivor14 r0  
    /* IVOR15 Debug interrupt (SPR 415) */
    mtivor15 r0 

    /* IVOR32 SPE APU unavailable interrupt (SPR 528) */
    mtivor32 r0 
    /* IVOR33 SPE floating-point data exception interrupt (SPR 529) */
    mtivor33 r0 
    /* IVOR34 SPE floating-point round exception interrupt (SPR 530) */
    mtivor34 r0

#endif

    blr
}
#ifdef __cplusplus
}
#endif

